import Doc from '~/components/layout/docs'
import { InlineCode } from '~/components/text/code'
import Caption from '~/components/text/caption'
import Note from '~/components/text/note'

export const meta = {
  title: 'Edge Cache for Serverless Functions',
  description:
    'Learn how Serverless Function responses are cached with ZEIT Now and how you can define the cache behavior.',
  editUrl: 'pages/docs/v2/serverless-functions/edge-caching.mdx',
  lastEdited: '2019-12-18T17:13:57.000Z'
}

The ZEIT Smart CDN is active for all deployments and domains on your account and caches your content at [the edge](/docs/v2/network/regions-and-providers/) to serve data to your users as fast as possible.

The Smart CDN is available for all of our [pricing plans](/docs/v2/platform/limits#plans) (including the Free plan) and can be activated for [Serverless Functions](/docs/v2/serverless-functions/introduction) by providing [`Cache-Control` headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control).

If `Cache-Control` headers are provided **all dynamic responses** from Serverless Functions will be cached in **all regions**.

## What is Cached?

Responses with a HTTP status of `200` to a `GET` or `HEAD` request are cached by our Smart CDN. Other status codes are never cached.

Additionally, the following are not cached:

- Responses that exceed 10MB in content length.
- Requests that contain the `Range` header.
- Requests that contain the `Authorization` or `Pragma` headers.
- Responses that contain the `no-cache` directive in their `Cache-Control` headers.

## Cache Control

When providing a `Cache-Control` is sent from your Serverless Function, it can include any of the following directives, separated by a comma:

- `s-maxage=N`
- `max-age=N, public`
- `max-age=N, immutable`

<Note>
  Above; where <InlineCode>N</InlineCode> is the number of seconds the response
  should be cached for.
</Note>

As an example, you can set the `Cache-Control` header in your [Node.js Serverless Functions](/docs/v2/serverless-functions/supported-languages#node.js) by using the `response.setHeader` method:

```js
module.exports = (request, response) => {
  response.setHeader('Cache-Control', 's-maxage=86400')
  response.send('Hello world!')
}
```

<Caption>
  A Node.js Serverless Function that sends a string response and caches that
  response for a day.
</Caption>

### Recommended `Cache-Control`

We recommend that you set your cache to have `max-age=0, s-maxage=86400`, with changing `86400` to the amount of seconds you want your response to be cached for.

This recommendation will tell browsers not to cache and let our edge cache the responses and invalidate when your deployments update, so you never have to worry about stale content.

### `stale-while-revalidate`

The Smart CDN supports a powerful recent extension to the `Cache-Control` header called `stale-while-revalidate`.

The benefit of using `stale-while-revalidate` is that we can serve a resource from our CDN cache while simultaneously updating the cache **in the background** with the response from your Serverless Function.

Some situations where `stale-while-revalidate` is of great value:

- Your content changes frequently but it takes a significant amount of time to regenerate. For example, an expensive database query or upstream API request.
- Your content changes infrequently but you want to have the flexibility to update it (to fix a typo, for example) and don't wait for cache to expire.

In both cases, we recommend using:

```
Cache-Control: s-maxage=1, stale-while-revalidate
```

Which tells our CDN: serve from cache, but update it, if requested after 1 second.

When the CDN receives a request with `Pragma: no-cache` (such as when the browser devtools are open), it will revalidate any stale resource synchronously, instead of in the background.

## Cache Invalidation and Purging

Every time you deploy with [a custom domain](/docs/v2/custom-domains#deploying-with-your-domain), the cache for that domain is purged. This means that users will never see content from a previous deployment on your custom domain and there is no need to invalidate it manually when deploying.

export default ({ children }) => <Doc meta={meta}>{children}</Doc>

export const config = {
  amp: 'hybrid'
}
